package com.gitee.huanminabc.utils_common.obj.proxy.jdk;


import com.gitee.huanminabc.jcommon.exception.CommonException;
import com.gitee.huanminabc.utils_common.obj.proxy.ActionProxy;
import com.gitee.huanminabc.utils_common.obj.proxy.MethodImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * JDK动态代理工厂 ,代理的目标对象必须实现接口 或者就是接口
 * ActionProxy 和MethodImpl可以二选一
 * ActionProxy 用于对方法进行增强
 * MethodImpl 用于对接口进行统一逻辑实现,意思就是如果没有实现类那么我们可以使用这个来实现内部逻辑, 或者覆盖原始逻辑走自己的逻辑
 */
public class ProxyJdkFactory implements InvocationHandler {

    private Object target;
    private ActionProxy actionProxy;

    public ProxyJdkFactory(ActionProxy actionProxy, Object target) {
        this.actionProxy = actionProxy;
        this.target = target;
    }

    private MethodImpl methodImpl;

    public ProxyJdkFactory(MethodImpl methodImpl) {
        this.methodImpl = methodImpl;
    }

    /**
     * @param proxy  代理的对象也就是ServiceProxy他自己 ,为啥要用target因为proxy被包裹了一层用起来不方便
     * @param method 被代理的方法
     * @param args   被代理的方法传入的参数
     * @return 返回被代理方法的执行的结果
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //代理对象,对方法进行增强
        if (actionProxy != null && target != null) {
            Object invoke = null;
            try {
                actionProxy.before(method, args);
                invoke = actionProxy.round(target, method, args); //环绕处理
                if ("notUse".equals(invoke)) {
                    invoke = method.invoke(target, args);
                }
                invoke = actionProxy.returnBefore(method, args, invoke);
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                actionProxy.exceptionHandling(method, args, e);
                throw new CommonException(e);
            } finally {
                actionProxy.end(method, args);
            }

            return invoke;
        } else {
            //判断methodImpl是否为空
            if (methodImpl == null) {
                return method.invoke(target, args);
            }
            //代理接口,对所有接口进行统一逻辑实现
            return methodImpl.run(target,method, args);

        }

    }
}
